package main

import (
	"fmt"
)

/*
	不用除法来 做除法
*/
func main() {
	m, n := -307,-8
	//begin:=time.Now().Unix()
	res := function4(m,n)
	//end := time.Now().Unix()
	fmt.Println(res)
}

// 我们都可以想到的一个思路，就是用加法来模拟除法，但是我们这里要注意一个边界问题
// m=-(1<<31), n = -1, 这个情况相除是等于0的, 这个简单的只能满足正数情况下。
func function1(m,n int) (res int) {
	//if m == -(1<<31)&&
	for m >= n {
		m -= n
		res++
	}
	return
}
// 上面的每次只是相加一个除数，所以慢，如果每次加的除数是倍数相加的呢？下面就要这么实现
func function2(m,n int) (res int) {
	for m>=n {
		// multi 我们是用来确定一次性加几个除数的
		multi := 1
		for multi*n <= m{
			multi<<=1
		}
		multi >>= 1
		res += multi
		m -= multi*n
	}
	return
}

// 引申是不用加减实现加法
// 俩个数用异或操作模拟不进位加法运算，用俩个数的与运算模拟进位，但是要考虑的是，与运算完需要左移一位，才是之后进位要加的位置。
func function3(m,n int) int{
	sum := 0
	carry := -1
	for carry != 0 {
		sum = m ^ n
		carry = (m & n)<<1
		m = sum
		n = carry
	}
	return sum
}

// 引申： 不用加减乘除实现减法
//  一个数进行取反：^1 = -2; ^-2 = 1
func function4(m,n int) int {
	res := m + ^n + 1
	return res
}

// 引申：用位运算实现乘法
func function5(m,n int) int {
	flag := false
	if (m>0 &&n>0) ||(m<0&&n<0){
		flag = true
	}
	if n < 0 {
		n = ^n + 1
	}
	if m < 0 {
		m = ^m + 1
	}
	res := 0
	bit_poistion := make(map[int]int)
	// 因为2的n次方的二进制中，只有一位是1,故用2的n次方进行进制模拟
	for i:=0; i<32;i++{
		// 这句的意思是告诉我们，每个位置的编号
		bit_poistion[1<<uint(i)] = i
	}
	for m > 0 {
		// 咱们要根据n的bit位将m向左移动对应编号位
		position := bit_poistion[m&^(m-1)]
		// 将n按照m的编号挪动
		res += n<<uint(position)
		// 将挪动后的那一位取消掉
		m &= m-1

	}
	if !flag {
		res = ^res + 1
	}
	return res
}